/*******************************************************************************
 * Copyright 2011 Alexandre Zglav and Morphiastic
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.morphiastic.dao;

import java.util.List;

import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.QueryBuilder;

import com.google.code.morphia.Key;
import com.google.code.morphia.dao.DAO;
import com.google.code.morphia.query.Query;
import com.google.code.morphia.query.UpdateOperations;
import com.google.code.morphia.query.UpdateResults;

public interface MorphiasticDAO<T, K> extends DAO<T, K>{

	
	List<T> getAll(List<K> keys);
	
	List<T> getAll();
	
	/**
	 * Perform a search against ElasticSearch index 
	 * 
	 * the SearchType will be SearchType.QUERY_THEN_FETCH
	 * 
	 * returning results from 0 to size-1
	 * 
	 * @param q the query builder that holds the actual query parameters (See http://www.elasticsearch.org/guide/reference/java-api/search.html 
	 * and  http://www.elasticsearch.org/guide/reference/query-dsl/ )
	 * @param size the number of results to return
	 * @return
	 */
	public SearchResponse search(QueryBuilder q, int size); 
	
	
	/**
	 * Perform a search against ElasticSearch index 
	 * 
	 * the SearchType will be SearchType.QUERY_THEN_FETCH
	 * 
	 * returning results from from param to size-1
	 * 
	 * @param q the query builder that holds the actual query parameters (See http://www.elasticsearch.org/guide/reference/java-api/search.html 
	 * and  http://www.elasticsearch.org/guide/reference/query-dsl/ )
	 * @param from the start of the result set
	 * @param size the number of results to return
	 * @return
	 */
	public SearchResponse search(QueryBuilder q, int from, int size);
	
	
	/**
	 * Perform a search against ElasticSearch index 
	 * 
	 * the SearchType will be SearchType.QUERY_THEN_FETCH
	 * 
	 * returning results from from param to size-1
	 * 
	 * @param q the query builder that holds the actual query parameters (See http://www.elasticsearch.org/guide/reference/java-api/search.html 
	 * and  http://www.elasticsearch.org/guide/reference/query-dsl/ )
	 * @param from the start of the result set
	 * @param size the number of results to return
	 * @param includeDescendants should we include the descendants of this entity : for example should a query on Shape also return 
	 * Circles and squares or should we ONLY get the entities that have been indexed as a Shape. Defaults to TRUE
	 * @return
	 */
	public SearchResponse search(QueryBuilder q, int from, int size, boolean includeDescendants); 
	
	/**
	 *  Perform a search against ElasticSearch index
	 *  
	 *  returning results from "from" param to size-1
	 * 
	 * @param q the query builder that holds the actual query parameters (See http://www.elasticsearch.org/guide/reference/java-api/search.html 
	 * and  http://www.elasticsearch.org/guide/reference/query-dsl/ )
	 * @param from the start of the result set
	 * @param size the number of results to return
	 * @return
	 *   
	 * @param q
	 * @param from
	 * @param size
	 * @param searchType the type of search to perform
	 * @param includeDescendants should we include the descendants of this entity : for example should a query on Shape also return 
	 * Circles and squares or should we ONLY get the entities that have been indexed as a Shape. Defaults to TRUE
	 * @return
	 */
	public SearchResponse search(QueryBuilder q, int from, int size, SearchType searchType, boolean includeDescendants); 
	
	
	/**
	 * Perform a search using a customized searchRequest builder wich allows for more fine grained tuning
	 * Before being fired the srb is provided with the associated types of the DAO entity Class
	 * @param searchRequestBuilder
	 * @return
	 */
	public SearchResponse search(SearchRequestBuilder searchRequestBuilder, boolean includeDescendants);
	
	
	
	/**
	 * Performs a Search and actually fetches the results from the data store using the object's ID
	 * 
	 * @param q
	 * @param from
	 * @param size
	 * @param searchType
	 * @param includeDescendants
	 * @return
	 */
	public List<T> searchAndFetch(QueryBuilder q, int from, int size, SearchType searchType, boolean includeDescendants);
	
	
	
	
	
	/**
	 * perform a search that we will be able to iterate upon
	 * 
	 *  the SearchType will be SearchType.SCAN
	 *  with a scroll time of 60000 (1 minute) 
	 *  and "size" hits per shard will be returned for each scroll
	 * 
	 * @param q
	 * @param size
	 * @return
	 */
	public SearchResponse searchScan(QueryBuilder q, int size);
	
	/**
	 * perform a search that we will be able to iterate upon
	 * 
	 *  the SearchType will be SearchType.SCAN
	 *  with a scroll time of 60000 (1 minute) 
	 *  and "size" hits per shard will be returned for each scroll
	 * 
	 * @param q
	 * @param size 
	 * @param scrollTimeMillis indicates for how long the nodes that participate in the search will 
	 * maintain relevant resources in order to continue and support it
	 * @return
	 */
	public SearchResponse searchScan(QueryBuilder q, int size, long scrollTimeMillis, boolean includeDescendants);
	
	/**
	 * index only : 
	 * the entity is not actually saved to the MongoDBServer
	 * @param entity
	 */
	public void index(T entity);
	
	/**
	 * Save Entity without indexing
	 * @param entity
	 */
	public Key<T> saveOnly(T entity);
	
	/**
	 * Perform Update Operations without indexing
	 * @param q
	 * @param ops
	 * @return
	 */
	public  UpdateResults<T> updateOnly(Query<T> q, UpdateOperations<T> ops);
	
	
	
	
	public Client getElasticClient();
	
	public String getGlobalElasticIndexname();
	
	
	
}
